package com.cumt.framework.rest.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cumt.framework.domain.BaseEntity;
import com.cumt.framework.dubbo.DubboBaseInterface;
import com.cumt.framework.exception.DubboProviderException;
import com.cumt.framework.rest.BaseRestServerInterface;
import com.cumt.framework.rest.view.JsonViewResponse;
import com.cumt.framework.rest.view.Page;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by caicf on 2016/12/27.
 */
@RestController
public abstract class BaseRestServerInterfaceImpl<Entity extends BaseEntity> implements BaseRestServerInterface {

    protected Logger log = LoggerFactory.getLogger(this.getClass());

    private static ThreadLocal<ServletRequest> currentRequest = new ThreadLocal<>();
    private static ThreadLocal<ServletResponse> currentResponse = new ThreadLocal<>();
    private static ThreadLocal<JsonViewResponse> currentJsonView = new ThreadLocal<>();

    /**
     * 基类公共方法，所有方法执行前都会先执行以下方法。
     * 线程安全初始化request，response对象
     */
    @ModelAttribute
    protected void initReqAndRep(HttpServletRequest request, HttpServletResponse response) {
        currentRequest.set(request);
        currentResponse.set(response);
    }

    @ModelAttribute
    protected void initJsonView() {
        currentJsonView.set(new JsonViewResponse());
    }

    protected HttpSession getSession() {
        return request().getSession();
    }

    protected JsonViewResponse jsonView() {
        return currentJsonView.get();
    }

    protected HttpServletRequest request() {
        return (HttpServletRequest) currentRequest.get();
    }

    protected HttpServletResponse response() {
        return (HttpServletResponse) currentResponse.get();
    }

    /**
     * 得到当前的对象class
     *
     * @return
     */
    public Class<Entity> getEntityClass() {
        Class<Entity> cls = null;
        ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
        Type type = genericSuperclass.getActualTypeArguments()[0];
        if (type instanceof Class) {
            cls = (Class<Entity>) type;
        } else if (type instanceof ParameterizedType) {
            cls = (Class<Entity>) ((ParameterizedType) type).getRawType();
        }
        return cls;
    }

    protected abstract DubboBaseInterface<Entity> getDubboBaseInterface();

    @Override
    public String getAll() {
        try {
            List<Entity> entities = this.getDubboBaseInterface().findAll();
            JSON result = (JSON) JSON.toJSON(entities);
            jsonView().successPack(result);
        } catch (DubboProviderException e) {
            jsonView().failPack(e);
            e.printStackTrace();
        }
        return toJsonStr(jsonView());
    }

    @Override
    public String getPage(@RequestBody String jsonStr) {
        JSON result;
        Page page;
        try {
            Map<String, Object> mapBean = Maps.newHashMap();
            if (!Strings.isNullOrEmpty(jsonStr)) {
                page = JSON.parseObject(jsonStr, Page.class);
                if (page != null) {
                    Entity entity = null;
                    if (page.getCondition() != null) {
                        JSON condition = JSON.parseObject(page.getCondition().toString());
                        mapBean = (Map<String, Object>) condition;
                    }
                }
            } else {
                page = new Page();
            }
            page = this.getDubboBaseInterface().findByPage(page, mapBean);
            result = (JSON) JSON.toJSON(page);
            jsonView().successPack(result);
        } catch (Exception e) {
            jsonView().failPack(e);
            e.printStackTrace();
        }
        return toJsonStr(jsonView());
    }

    @Override
    public String getByWhere(@RequestBody String jsonStr) {
        JSON result;
        try {
            Entity entity = JSON.parseObject(jsonStr, this.getEntityClass());
            if (entity != null) {
                Map<String, Object> mapBean = (Map<String, Object>) JSON.toJSON(entity);
                List<Entity> list = this.getDubboBaseInterface().findByMap(mapBean);
                if (list != null) {
                    result = (JSON) JSON.toJSON(list);
                } else {
                    result = new JSONArray();
                }
                jsonView().successPack(result);
            }
        } catch (Exception e) {
            jsonView().failPack(e);
            log.error("BaseRestServerInterfaceImpl getByWhere is error，{jsonStr:" + jsonStr + "}", e);
        }
        return toJsonStr(jsonView());
    }

    @Override
    public String getById(@PathVariable("id") int id) {
        JSON result;
        try {
            Entity entity = this.getDubboBaseInterface().findById(id);
            if (entity != null) {
                result = (JSON) JSON.toJSON(entity);
            } else {
                result = new JSONObject();
            }
            jsonView().successPack(result);
        } catch (DubboProviderException e) {
            jsonView().failPack(e);
            e.printStackTrace();
        }
        return toJsonStr(jsonView());
    }

    @Override
    public String deleteByIds(@RequestParam("id") String ids) {
        try {
            if (!Strings.isNullOrEmpty(ids)) {
                String[] idsToDel = ids.split(",");
                List<Integer> param = new ArrayList<>(idsToDel.length);
                for (String s : idsToDel) {
                    param.add(Integer.valueOf(s));
                }
                boolean flag = this.getDubboBaseInterface().deleteById(param);
                if (flag) {
                    jsonView().successPack("删除成功！");
                } else {
                    jsonView().failPack("删除失败！");
                }
            }
        } catch (DubboProviderException e) {
            jsonView().failPack(e);
            e.printStackTrace();
        }
        return toJsonStr(jsonView());
    }

    @Override
    public String save(@RequestBody String jsonStr) {
        try {
            System.out.println(jsonStr);
            if (!Strings.isNullOrEmpty(jsonStr) && !"{}".equalsIgnoreCase(jsonStr)) {
                Entity entity = JSON.parseObject(jsonStr, this.getEntityClass());
                if (entity != null) {
                    boolean flag = this.getDubboBaseInterface().save(entity);
                    if (flag) {
                        jsonView().successPack("保存数据成功!");
                    } else {
                        jsonView().failPack("保存数据失败!");
                    }
                }
            } else {
                jsonView().failPack("保存数据失败!");
            }
        } catch (Exception e) {
            jsonView().failPack("false", "保存数据失败！" + e.getMessage());
        }
        return toJsonStr(jsonView());
    }

    @Override
    public String update(@RequestBody String jsonStr) {
        try {
            Entity entity = JSON.parseObject(jsonStr, this.getEntityClass());
            if (entity != null) {
                boolean res = this.getDubboBaseInterface().update(entity);
                if (res) {
                    jsonView().successPack("更新成功！");
                } else {
                    jsonView().failPack("更新失败！");
                }
            }
        } catch (Exception e) {
            jsonView().failPack(e);
        }
        return toJsonStr(jsonView());
    }

    @Override
    public String toJsonStr(JsonViewResponse jsonView) {
        return JSON.toJSONStringWithDateFormat(jsonView, "yyyy-MM-dd HH:mm:ss");
    }
}
